import datetime
import logging
import os
import sys
from pathlib import Path

import pywintypes
import win32gui
from PyQt5.QtGui import QIcon
from PyQt5.QtWidgets import QWidget, QPushButton, QMessageBox
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import QApplication
import vlc
import platform


log_path = Path() / 'log'
if not log_path.exists():
    log_path.mkdir(parents=True, exist_ok=True)

# 配置日志
console_level = logging.INFO
file_level = logging.INFO
file_handler = logging.FileHandler(f'./log/{datetime.datetime.now().strftime("%Y-%m-%d-%H.%M.%S")}.txt', mode='a', encoding="utf8")
file_handler.setFormatter(logging.Formatter('%(asctime)s [%(levelname)s] %(module)s.%(lineno)d %(name)s:%(message)s'))
file_handler.setLevel(file_level)
console_handler = logging.StreamHandler(sys.stdout)
console_handler.setFormatter(logging.Formatter('[%(asctime)s %(levelname)s] %(message)s', datefmt="%Y/%m/%d %H:%M:%S"))
console_handler.setLevel(console_level)
logging.basicConfig(level=min(console_level, file_level), handlers=[file_handler, console_handler],)


class Panel(QWidget):

    def __init__(self, instance, player):
        super().__init__()

        self.instance = instance
        self.player = player
        self.audioChannel = 0  # 0 原始音效  5 杜比音效
        self.hardwareDecode = True
        self.userPause = False
        self.cacheFolder = None
        self.cacheName = None
        self.media = None
        self.progress = 0
        self.stopTimes = 0
        self.index = 0
        self.fileList = []
        self.length = 0

        if self.cacheFolder is None:
            path = Path() / 'cache'
            if not path.exists():
                path.mkdir(parents=True, exist_ok=True)
            self.cacheFolder = path

        # 获取文件
        file_name_list = os.listdir(self.cacheFolder)
        self.fileList = file_name_list
        self.length = len(self.fileList)

        # 实例化 player
        self.newPlayer()

        self.audioBut = QPushButton('静音/取消', self)
        self.audioFlag = False
        self.hiddenBut = QPushButton('隐藏/取消', self)
        self.hiddenFlag = False
        self.playBut = QPushButton('暂停/播放', self)
        self.playFlag = False
        self.nextBut = QPushButton('切换视频', self)
        self.reloadBut = QPushButton('重载文件', self)
        self.initUI()

        # 检查播放卡住的定时器
        self.checkPlaying = QTimer()
        self.checkPlaying.timeout.connect(self.checkPlayStatus)
        self.checkPlaying.start(1000)

    def checkPlayStatus(self):
        if self.userPause:
            return
        self.progress = self.player.get_time()
        if not self.player.is_playing() and not self.isHidden():
            if self.player.get_time() <= self.progress + 1:
                self.setMediaAuto()
                return
            self.stopTimes += 1
        if self.stopTimes >= 5:
            self.setMediaAuto(True)

    def setMediaAuto(self, flag: bool = False):
        if self.length == 0:
            QMessageBox.information(self, "提示", f"cache文件夹中未发现视频文件", QMessageBox.Yes)
            self.userPause = True
            return
        if self.index >= self.length:
            self.index = 0
        if flag:
            if self.length == 0:
                self.setMedia(self.cacheFolder / self.fileList[self.index])
            else:
                if self.index == 0:
                    path = self.cacheFolder / self.fileList[self.length - 1]
                else:
                    path = self.cacheFolder / self.fileList[self.index-1]
                self.setMedia(path)
            self.player.set_time(self.progress)
            return
        else:
            self.setMedia(self.cacheFolder / self.fileList[self.index])
        self.index += 1

    def setMedia(self, cacheName):
        self.cacheName = cacheName

        if self.hardwareDecode:
            self.media = self.instance.media_new(cacheName, 'avcodec-hw=any')  # 设置vlc并硬解播放
        else:
            self.media = self.instance.media_new(cacheName, 'avcodec-hw=none')  # 软解  vlc3.0似乎不起作用?
        self.player.set_media(self.media)  # 设置视频
        self.player.audio_set_channel(self.audioChannel)
        self.player.play()

    def newPlayer(self):
        """
        实例化 player
        依赖实例化的 vlc （self.instance）
        """
        self.player = self.instance.media_player_new()  # 视频播放
        self.player.video_set_mouse_input(False)
        self.player.video_set_key_input(False)
        # 将播放器实例绑定到桌面句柄
        if platform.system() == 'Windows':
            hwnd = removeWorkW()
            self.player.set_hwnd(hwnd)
        elif platform.system() == 'Darwin':  # for MacOS
            pass
        else:
            pass

    def initUI(self):
        self.setGeometry(0, 0, 600, 300)
        self.setWindowTitle('控制台')
        self.setWindowIcon(QIcon('diana.ico'))
        self.audioBut.setGeometry(0, 20, 100, 50)
        self.audioBut.clicked.connect(self.audioFunc)
        self.hiddenBut.setGeometry(100, 20, 100, 50)
        self.hiddenBut.clicked.connect(self.hiddenFunc)
        self.playBut.setGeometry(200, 20, 100, 50)
        self.playBut.clicked.connect(self.playFunc)
        self.nextBut.setGeometry(300, 20, 100, 50)
        self.nextBut.clicked.connect(self.nextFunc)
        self.reloadBut.setGeometry(400, 20, 100, 50)
        self.reloadBut.clicked.connect(self.reloadFunc)
        self.show()

    def audioFunc(self):
        self.audioFlag = not self.audioFlag
        if self.audioFlag:
            self.player.audio_set_volume(0)
        else:
            self.player.audio_set_volume(100)

    def hiddenFunc(self):
        self.hiddenFlag = not self.hiddenFlag
        if self.hiddenFlag:
            self.userPause = True
            self.player.release()
        else:
            self.newPlayer()
            self.setMediaAuto(True)
            self.userPause = False

    def playFunc(self):
        self.playFlag = not self.playFlag
        if self.playFlag:
            self.userPause = True
            self.player.pause()
        else:
            self.player.set_pause(0)
            self.userPause = False

    def nextFunc(self):
        if self.hiddenFlag:
            self.hiddenFunc()
        if self.length == 1:
            QMessageBox.information(self, "提示", f"当前视频文件仅有一个，无法切换到下一个", QMessageBox.Yes)
            return
        self.setMediaAuto()
        self.userPause = False

    def reloadFunc(self):
        file_name_list = os.listdir(self.cacheFolder)
        self.fileList = file_name_list
        self.length = len(self.fileList)
        QMessageBox.information(self, "提示", f"加载完成,当前共有{self.length}个视频文件", QMessageBox.Yes)


def getHandle():
    """
    获取windows桌面handle
    已弃用
    """
    hwnd = win32gui.FindWindow("Progman", "Program Manager")
    a = win32gui.SendMessageTimeout(hwnd, 0x052C, 0, None, 0, 0x03E8)
    hwnd_WorkW = None
    while 1:
        hwnd_WorkW = win32gui.FindWindowEx(None, hwnd_WorkW, "WorkerW", None)
        # print("hwnd_WorkW: ",hwnd_WorkW)
        if not hwnd_WorkW:
            continue
        hView = win32gui.FindWindowEx(hwnd_WorkW, None, "SHELLDLL_DefView", None)
        # print('hwmd_hView: ', hView)
        if not hView:  # 这个WorkerW下没有shell
            continue
        h = win32gui.FindWindowEx(None, hwnd_WorkW, "WorkerW", None)
        while h:
            win32gui.SendMessage(h, 0x0010, 0, 0)  # WM_CLOSE
            h = win32gui.FindWindowEx(None, hwnd_WorkW, "WorkerW", None)
        break
    return hwnd


def _callback(hwnd, extra):
    # print(hex(hwnd), win32gui.GetClassName(hwnd))
    temp = [extra[1][0], hwnd]
    extra[0][win32gui.GetClassName(hwnd)] = temp
    extra[1][0] += 1


def removeWorkW():
    w = {}
    count = [0]
    extra = w, count
    hwnd = win32gui.FindWindow('Progman', None)
    win32gui.SendMessage(hwnd, 0x052c, 0, 0)
    win32gui.EnumWindows(_callback, extra)
    workerW_count = w['Progman'][0] - 1
    Progman_hwnd = w['Progman'][1]
    for className in w:
        if w[className][0] == workerW_count:
            if win32gui.FindWindowEx(w[className][1], 0, 'SHELLDLL_DefView', None):
                pass
            else:
                workerW_hwnd = w[className][1]
                win32gui.SendMessage(workerW_hwnd, 16, 0, 0)
    return Progman_hwnd


if __name__ == '__main__':
    Instance = vlc.Instance()
    Player = Instance.media_player_new()
    app = QApplication(sys.argv)
    panel = Panel(Instance, Player)
    app.exec_()
